package com.wyw.learning.thread.cas;

/**
 * 模拟CAS，等价代码
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
public class TwoThreadsCompetitiom implements Runnable {
    /*
        为什么CAS修改的变量必须使用valatile
        这里使用了synchrozied修饰了方法，已经保证了变量的可见性，但是退出synchrozied之后,才能保证变量的可见性，所以加上volatile修饰，以便在各个线程之间保证可见

        退出synchronized之后，别的线程拿到锁，根据happens-before原则，就能看到变量更新后的值。退出synchronized块之前happens-before原则不生效
        本例子比较简单，在退出synchronized块前不会有其他线程修改变量value的值，所以，这里起始也可以不需要volatile，但是理论上是需要的
     */
    private volatile int value;

    /**
     *  被synchrozied修饰的代码块在CPU执行过程中可以切换出去
     *  但是不能有其他线程进来干扰，宏观层面是源自的，但是站在CPU指令的角度，不是原子的
     */
    public synchronized int compareAndSwap(int expectedValue, int newValue) {
        int oldValue = value;
        if(oldValue == expectedValue) {
            value = newValue;
        }
        return oldValue;
    }

    public static void main(String[] args) throws InterruptedException {
//        new AtomicInteger();
        TwoThreadsCompetitiom r = new TwoThreadsCompetitiom();
        r.value = 0;
        Thread t1 = new Thread(r, "Thread 1");
        Thread t2 = new Thread(r, "Thread 2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(r.value);
    }

    @Override
    public void run() {
        compareAndSwap(0,1);
    }
}
